Add Address Sanitizer support to std::vector git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@208319 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/vector b/include/vector index 6ac78d5..2cc23e5 100644 --- a/include/vector +++ b/include/vector
@@ -483,6 +483,7 @@ { private: typedef __vector_base<_Tp, _Allocator> __base; + typedef allocator<_Tp> __default_allocator_type; public: typedef vector __self; typedef _Tp value_type; @@ -749,7 +750,9 @@ _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT { + size_type __old_size = size(); __base::clear(); + __annotate_shrink(__old_size); __invalidate_all_iterators(); } @@ -816,7 +819,9 @@ } __get_db()->unlock(); #endif + size_type __old_size = size(); __base::__destruct_at_end(__new_last); + __annotate_shrink(__old_size); } template <class _Up> void @@ -830,17 +835,52 @@ void __emplace_back_slow_path(_Args&&... __args); #endif + // The following functions are no-ops outside of AddressSanitizer mode. + // We call annotatations only for the default Allocator because other allocators + // may not meet the AddressSanitizer alignment constraints. + // See the documentation for __sanitizer_annotate_contiguous_container for more details. + void __annotate_contiguous_container + (const void *__beg, const void *__end, const void *__old_mid, const void *__new_mid) + { +#ifndef _LIBCPP_HAS_NO_ASAN + if (__beg && is_same<allocator_type, __default_allocator_type>::value) + __sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid); +#endif + } + + void __annotate_new(size_type __current_size) + { + __annotate_contiguous_container(data(), data() + capacity(), + data() + capacity(), data() + __current_size); + } + void __annotate_delete() + { + __annotate_contiguous_container(data(), data() + capacity(), + data() + size(), data() + capacity()); + } + void __annotate_increase(size_type __n) + { + __annotate_contiguous_container(data(), data() + capacity(), + data() + size(), data() + size() + __n); + } + void __annotate_shrink(size_type __old_size) + { + __annotate_contiguous_container(data(), data() + capacity(), + data() + __old_size, data() + size()); + } }; template <class _Tp, class _Allocator> void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) { + __annotate_delete(); __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_); _VSTD::swap(this->__begin_, __v.__begin_); _VSTD::swap(this->__end_, __v.__end_); _VSTD::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; + __annotate_new(size()); __invalidate_all_iterators(); } @@ -848,6 +888,7 @@ typename vector<_Tp, _Allocator>::pointer vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p) { + __annotate_delete(); pointer __r = __v.__begin_; __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_); __alloc_traits::__construct_forward(this->__alloc(), __p, this->__end_, __v.__end_); @@ -855,6 +896,7 @@ _VSTD::swap(this->__end_, __v.__end_); _VSTD::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; + __annotate_new(size()); __invalidate_all_iterators(); return __r; } @@ -874,6 +916,7 @@ this->__throw_length_error(); this->__begin_ = this->__end_ = __alloc_traits::allocate(this->__alloc(), __n); this->__end_cap() = this->__begin_ + __n; + __annotate_new(0); } template <class _Tp, class _Allocator> @@ -920,6 +963,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n) { allocator_type& __a = this->__alloc(); + __annotate_increase(__n); do { __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_)); @@ -940,6 +984,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) { allocator_type& __a = this->__alloc(); + __annotate_increase(__n); do { __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), __x); @@ -960,6 +1005,7 @@ allocator_type& __a = this->__alloc(); for (; __first != __last; ++__first) { + __annotate_increase(1); __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first); ++this->__end_; } @@ -972,6 +1018,7 @@ allocator_type& __a = this->__alloc(); for (; __first != __last; ++__first) { + __annotate_increase(1); __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), _VSTD::move(*__first)); ++this->__end_; @@ -1535,6 +1582,7 @@ { if (this->__end_ != this->__end_cap()) { + __annotate_increase(1); __alloc_traits::construct(this->__alloc(), _VSTD::__to_raw_pointer(this->__end_), __x); ++this->__end_; @@ -1552,6 +1600,7 @@ { if (this->__end_ < this->__end_cap()) { + __annotate_increase(1); __alloc_traits::construct(this->__alloc(), _VSTD::__to_raw_pointer(this->__end_), _VSTD::move(__x)); @@ -1584,6 +1633,7 @@ { if (this->__end_ < this->__end_cap()) { + __annotate_increase(1); __alloc_traits::construct(this->__alloc(), _VSTD::__to_raw_pointer(this->__end_), _VSTD::forward<_Args>(__args)...); @@ -1666,6 +1716,7 @@ pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { + __annotate_increase(1); if (__p == this->__end_) { __alloc_traits::construct(this->__alloc(), @@ -1705,6 +1756,7 @@ pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { + __annotate_increase(1); if (__p == this->__end_) { __alloc_traits::construct(this->__alloc(), @@ -1743,6 +1795,7 @@ pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { + __annotate_increase(1); if (__p == this->__end_) { __alloc_traits::construct(this->__alloc(), @@ -1794,6 +1847,7 @@ } if (__n > 0) { + __annotate_increase(__n); __move_range(__p, __old_last, __p + __old_n); const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x); if (__p <= __xr && __xr < this->__end_) @@ -1904,6 +1958,7 @@ } if (__n > 0) { + __annotate_increase(__n); __move_range(__p, __old_last, __p + __old_n); _VSTD::copy(__first, __m, __p); }